package org.ichihamigua.common.qiniucloud.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Client;
import com.qiniu.storage.*;
import com.qiniu.util.Auth;
import org.ichihamigua.common.framework.entity.Result;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.ichihamigua.common.qiniucloud.config.QiniuConfig;
import org.ichihamigua.common.qiniucloud.vo.UploadPartVo;
import org.ichihamigua.common.qiniucloud.service.QiniuRequestService;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;

/**
 * @author rainkyzhong
 * @date 2023/10/29 12:06
 */
@Service
@Slf4j
public class QiniuRequestServiceImpl implements QiniuRequestService {


    private final static String HOST = "up-z2.qiniup.com";

    @Resource
    private QiniuConfig config;

    @Resource
    private RestTemplate restTemplate;

    @Override
    public Auth getAuth(){
        return Auth.create(config.getAccessKey(), config.getSecretKey());
    }

    private final Client client = new Client(new Configuration(Region.region0()));

    @Override
    public Result<UploadPartVo> uploadPart(String bucketName, String uploadId, Integer partNumber, String key, MultipartFile file){
        ApiUploadV2UploadPart uploader = new ApiUploadV2UploadPart(client);
        try {
            byte[] bytes = file.getBytes();
            ApiUploadV2UploadPart.Request request = new ApiUploadV2UploadPart.Request(
                    "http://"+HOST,
                    getAuth().uploadToken(bucketName),
                    uploadId,
                    partNumber
            ).setKey(key).setUploadData(bytes, 0, bytes.length, MediaType.MULTIPART_FORM_DATA.getType());
            ApiUploadV2UploadPart.Response response = uploader.request(request);
            UploadPartVo uploadPartVo = new UploadPartVo();
            uploadPartVo.setPartNumber(partNumber);
            uploadPartVo.setEtag(response.getEtag());
            return Result.success(uploadPartVo);
        } catch (QiniuException e){
            e.printStackTrace();
            return Result.fail(e.error());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 发起请求
     * @param api API
     * @param data 数据
     * @return 响应参数
     */
    @Override
    public <T> Result<T> request(String api, String bucketName, HttpMethod methodType, JSONObject data, HttpHeaders headers, Class<T> responseType){
        String url = "http://"+ HOST + api;
        //构造请求数据
        if (data == null) data = new JSONObject();
        //构造请求头
        if(headers == null) headers = new HttpHeaders();
        headers.add("Host", HOST);
        headers.add("Authorization",
                "UpToken "+getAuth().uploadToken(bucketName)
        );
        try {
            ResponseEntity<String> res;
            HttpEntity<JSONObject> req;
            if (methodType.equals(HttpMethod.GET)){
                req = new HttpEntity<>(headers);
                if(data.size() > 0) {
                    StringBuilder paramsBuilder = new StringBuilder();
                    data.forEach((k, v) -> paramsBuilder.append("&").append(paramsBuilder).append("=").append(v));
                    url += "?" + paramsBuilder.substring(1);
                }
            }else{
                req = new HttpEntity<>(data, headers);
            }
            res = restTemplate.exchange(url,methodType,req,String.class);
            if (res.getStatusCode().is2xxSuccessful()) {
                return Result.success(JSONObject.parseObject(res.getBody(), responseType));
            } else {
                JSONObject errRes = JSONObject.parseObject(res.getBody());
                if(errRes == null || !errRes.containsKey("error")){
                    log.error("接口请求出现异常 {} {} {} {}", methodType, url, data, res);
                    return Result.fail("接口请求失败");
                }
                return Result.fail(errRes.getString("error"));
            }
        }catch (Exception e) {
            log.error("接口请求出现异常 {} {} {} {}", methodType, url, data, e.getMessage());
            e.printStackTrace();
            return Result.fail("接口请求失败");
        }
    }
}
